#!/usr/bin/env python3
"""
后台图片上传服务器
支持图片上传、压缩、存储和API接口
"""

import os
import json
import uuid
import logging
from datetime import datetime
from flask import Flask, request, jsonify, send_from_directory
from werkzeug.utils import secure_filename
from PIL import Image
import io

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = Flask(__name__)

# 配置
UPLOAD_FOLDER = 'static/uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp'}
MAX_FILE_SIZE = 10 * 1024 * 1024  # 10MB
COMPRESS_QUALITY = 85

# 确保上传目录存在
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = MAX_FILE_SIZE

def allowed_file(filename):
    """检查文件类型是否允许"""
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def compress_image(image_data, max_width=1920, max_height=1080):
    """压缩图片"""
    try:
        image = Image.open(io.BytesIO(image_data))
        
        # 转换为RGB模式（如果不是）
        if image.mode in ('RGBA', 'LA', 'P'):
            # 创建白色背景
            background = Image.new('RGB', image.size, (255, 255, 255))
            if image.mode == 'P':
                image = image.convert('RGBA')
            background.paste(image, mask=image.split()[-1] if image.mode == 'RGBA' else None)
            image = background
        elif image.mode != 'RGB':
            image = image.convert('RGB')
        
        # 计算缩放比例
        width, height = image.size
        if width > max_width or height > max_height:
            ratio = min(max_width / width, max_height / height)
            new_size = (int(width * ratio), int(height * ratio))
            image = image.resize(new_size, Image.Resampling.LANCZOS)
        
        # 保存压缩后的图片
        output = io.BytesIO()
        image.save(output, format='JPEG', quality=COMPRESS_QUALITY, optimize=True)
        return output.getvalue()
    except Exception as e:
        logger.error(f"图片压缩失败: {e}")
        return None

@app.route('/api/upload', methods=['POST'])
def upload_image():
    """处理图片上传"""
    try:
        if 'image' not in request.files:
            return jsonify({'error': '没有上传文件'}), 400
        
        file = request.files['image']
        if file.filename == '':
            return jsonify({'error': '文件名为空'}), 400
        
        if not allowed_file(file.filename):
            return jsonify({'error': '不支持的文件类型'}), 400
        
        # 读取文件数据
        file_data = file.read()
        if len(file_data) > MAX_FILE_SIZE:
            return jsonify({'error': '文件过大'}), 400
        
        # 压缩图片
        compressed_data = compress_image(file_data)
        if compressed_data is None:
            return jsonify({'error': '图片处理失败'}), 500
        
        # 生成唯一文件名
        file_extension = file.filename.rsplit('.', 1)[1].lower()
        unique_filename = f"{uuid.uuid4().hex}.{file_extension}"
        
        # 保存文件
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename)
        with open(file_path, 'wb') as f:
            f.write(compressed_data)
        
        # 生成文件信息
        file_info = {
            'original_name': secure_filename(file.filename),
            'filename': unique_filename,
            'size': len(compressed_data),
            'upload_time': datetime.now().isoformat(),
            'url': f'/static/uploads/{unique_filename}'
        }
        
        # 保存文件信息到JSON
        info_path = os.path.join(app.config['UPLOAD_FOLDER'], f"{unique_filename}.json")
        with open(info_path, 'w', encoding='utf-8') as f:
            json.dump(file_info, f, ensure_ascii=False, indent=2)
        
        logger.info(f"图片上传成功: {unique_filename}")
        
        return jsonify({
            'success': True,
            'message': '上传成功',
            'data': file_info
        })
        
    except Exception as e:
        logger.error(f"上传处理失败: {e}")
        return jsonify({'error': '上传失败'}), 500

@app.route('/api/images', methods=['GET'])
def get_images():
    """获取所有上传的图片列表"""
    try:
        images = []
        upload_dir = app.config['UPLOAD_FOLDER']
        
        # 遍历上传目录
        for filename in os.listdir(upload_dir):
            if filename.endswith('.json'):
                json_path = os.path.join(upload_dir, filename)
                try:
                    with open(json_path, 'r', encoding='utf-8') as f:
                        image_info = json.load(f)
                        images.append(image_info)
                except Exception as e:
                    logger.warning(f"读取图片信息失败: {json_path}, {e}")
        
        # 按上传时间排序（最新的在前）
        images.sort(key=lambda x: x.get('upload_time', ''), reverse=True)
        
        return jsonify({
            'success': True,
            'data': images,
            'total': len(images)
        })
        
    except Exception as e:
        logger.error(f"获取图片列表失败: {e}")
        return jsonify({'error': '获取图片列表失败'}), 500

@app.route('/api/delete/<filename>', methods=['DELETE'])
def delete_image(filename):
    """删除图片"""
    try:
        # 安全检查文件名
        if not allowed_file(filename):
            return jsonify({'error': '无效的文件名'}), 400
        
        # 删除图片文件
        image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        if os.path.exists(image_path):
            os.remove(image_path)
        
        # 删除信息文件
        info_path = os.path.join(app.config['UPLOAD_FOLDER'], f"{filename}.json")
        if os.path.exists(info_path):
            os.remove(info_path)
        
        logger.info(f"图片删除成功: {filename}")
        
        return jsonify({
            'success': True,
            'message': '删除成功'
        })
        
    except Exception as e:
        logger.error(f"删除图片失败: {e}")
        return jsonify({'error': '删除失败'}), 500

@app.route('/static/uploads/<filename>')
def uploaded_file(filename):
    """提供上传的图片文件"""
    try:
        # 安全检查文件名
        if not allowed_file(filename):
            return jsonify({'error': '无效的文件名'}), 400
        
        return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
        
    except Exception as e:
        logger.error(f"文件访问失败: {e}")
        return jsonify({'error': '文件访问失败'}), 404

@app.route('/api/stats', methods=['GET'])
def get_stats():
    """获取统计信息"""
    try:
        images = []
        upload_dir = app.config['UPLOAD_FOLDER']
        total_size = 0
        
        # 遍历上传目录
        for filename in os.listdir(upload_dir):
            if filename.endswith('.json'):
                json_path = os.path.join(upload_dir, filename)
                try:
                    with open(json_path, 'r', encoding='utf-8') as f:
                        image_info = json.load(f)
                        images.append(image_info)
                        total_size += image_info.get('size', 0)
                except Exception as e:
                    logger.warning(f"读取图片信息失败: {json_path}, {e}")
        
        return jsonify({
            'success': True,
            'data': {
                'total_images': len(images),
                'total_size': total_size,
                'total_size_formatted': format_file_size(total_size),
                'last_upload': images[0].get('upload_time') if images else None
            }
        })
        
    except Exception as e:
        logger.error(f"获取统计信息失败: {e}")
        return jsonify({'error': '获取统计信息失败'}), 500

def format_file_size(size_bytes):
    """格式化文件大小"""
    for unit in ['B', 'KB', 'MB', 'GB']:
        if size_bytes < 1024.0:
            return f"{size_bytes:.1f} {unit}"
        size_bytes /= 1024.0
    return f"{size_bytes:.1f} TB"

@app.route('/')
def index():
    """首页"""
    return jsonify({
        'message': '后台图片上传服务器',
        'version': '1.0.0',
        'endpoints': {
            'upload': '/api/upload',
            'images': '/api/images',
            'delete': '/api/delete/<filename>',
            'stats': '/api/stats'
        }
    })

if __name__ == '__main__':
    print("🚀 启动后台图片上传服务器...")
    print(f"📁 上传目录: {UPLOAD_FOLDER}")
    print(f"🌐 访问地址: http://localhost:5000")
    print("📋 API 端点:")
    print("  - POST /api/upload - 上传图片")
    print("  - GET /api/images - 获取图片列表")
    print("  - DELETE /api/delete/<filename> - 删除图片")
    print("  - GET /api/stats - 获取统计信息")
    
    app.run(host='0.0.0.0', port=5000, debug=True)